package com.socket.tools.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.socket.tools.model.Message;
import com.socket.tools.service.ConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket处理器
 * 处理客户端和服务端用户的WebSocket连接
 */
@Component
public class WebSocketHandler extends TextWebSocketHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(WebSocketHandler.class);

    private  static  final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private ConnectionManager connectionManager;
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    // 会话类型映射 (会话ID -> 用户类型)
    private final Map<String, String> sessionTypes = new ConcurrentHashMap<>();
    
    // 用户ID映射 (会话ID -> 用户ID)
    private final Map<String, String> sessionUsers = new ConcurrentHashMap<>();

    //建立连接之后
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String sessionId = session.getId();
        logger.info("WebSocket连接建立: {}", sessionId);
        logger.info("连接URI: {}", session.getUri());
        
        // 从URL参数中获取用户类型和用户ID
        String query = session.getUri().getQuery();
        String userType = null;
        String userId = null;
        
        logger.info("URL查询参数: {}", query);
        
        if (query != null) {
            String[] params = query.split("&");
            for (String param : params) {
                String[] kv = param.split("=");
                if (kv.length == 2) {
                    if ("type".equals(kv[0])) {
                        userType = kv[1];
                        logger.info("用户类型: {}", userType);
                    } else if ("id".equals(kv[0])) {
                        userId = kv[1];
                        logger.info("用户ID: {}", userId);
                    }
                }
            }
        }
        
        if ("admin".equals(userType) && userId != null) {
            // 服务端用户连接
            sessionTypes.put(sessionId, "admin");
            sessionUsers.put(sessionId, userId);
            connectionManager.registerAdmin(userId, session);
            connectionManager.updateAdminActivity(userId); // 更新活动时间
            
            // 发送欢迎消息
            Message welcomeMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                    "欢迎服务端用户 " + userId + "！您可以查看和处理客户端连接请求。");
            sendMessage(session, welcomeMsg);
            
            // 发送当前所有等待的连接请求
            List<ConnectionManager.ConnectionRequest> pendingRequests = connectionManager.getConnectionQueue();
            for (ConnectionManager.ConnectionRequest request : pendingRequests) {
                Message requestMsg = new Message(Message.MessageType.CONNECT_REQUEST, request.getClientName(), 
                        "新的连接请求 - 客户端: " + request.getClientName());
                requestMsg.setSessionId(request.getClientSessionId());
                requestMsg.setTimestamp(sdf.parse(connectionManager.getClientConnectTime().get(request.getClientSessionId())));
                sendMessage(session, requestMsg);
            }
            
            // 发送在线管理员信息
            List<String> onlineAdmins = connectionManager.getOnlineAdmins();
            Message adminListMsg = new Message(Message.MessageType.ONLINE_ADMINS, "系统", "");
            adminListMsg.setAdmins(onlineAdmins);
            sendMessage(session, adminListMsg);
            
            // 广播在线管理员更新给所有服务端用户
            broadcastOnlineAdminsUpdate();
            
            logger.info("服务端用户连接: {} ({})，发送了 {} 个等待的请求", userId, sessionId, pendingRequests.size());
            
        } else if ("client".equals(userType)) {
            // 客户端连接
            sessionTypes.put(sessionId, "client");
            sessionUsers.put(sessionId, sessionId); // 客户端使用会话ID作为用户ID
            connectionManager.registerClient(sessionId, session);
            
            // 发送欢迎消息
            Message welcomeMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                    "欢迎客户端用户！您可以点击按钮申请连接。");
            sendMessage(session, welcomeMsg);
            connectionManager.getClientConnectTime().put(sessionId,getNowStr());
            logger.info("客户端连接: {}", sessionId);
            
        } else {
            // 无效连接
            logger.warn("无效的WebSocket连接: {} - 用户类型: {}, 用户ID: {}", sessionId, userType, userId);
            session.close();
        }
    }
    
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //清理会话
        String sessionId = session.getId();
        String userType = sessionTypes.get(sessionId);
        
        logger.info("收到WebSocket消息: 会话ID={}, 用户类型={}, 消息内容={}", sessionId, userType, message.getPayload());
        
        try {
            Message msg = objectMapper.readValue(message.getPayload(), Message.class);
            logger.info("解析后的消息: 类型={}, 来源={}, 内容={}, 会话ID={}", 
                    msg.getType(), msg.getFrom(), msg.getContent(), msg.getSessionId());
            
            // 处理心跳消息
            if (msg.getType() == Message.MessageType.HEARTBEAT) {
                logger.debug("收到心跳消息: 会话ID={}", sessionId);
                // 更新活动时间
                if ("admin".equals(userType)) {
                    String adminId = sessionUsers.get(sessionId);
                    if (adminId != null) {
                        connectionManager.updateAdminActivity(adminId);
                    }
                }
                return;
            }
            
            if ("admin".equals(userType)) {
                logger.info("处理服务端用户消息");
                handleAdminMessage(session, msg);
            } else if ("client".equals(userType)) {
                logger.info("处理客户端消息");
                handleClientMessage(session, msg);
            } else {
                logger.warn("未知用户类型: {}", userType);
            }
            
        } catch (Exception e) {
            logger.error("处理消息失败: {}", e.getMessage(), e);
            Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                    "消息处理失败: " + e.getMessage());
            sendMessage(session, errorMsg);
        }
    }
    
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String sessionId = session.getId();
        String userType = sessionTypes.get(sessionId);
        String userId = sessionUsers.get(sessionId);
        
        logger.info("WebSocket连接关闭: {} ({}) - {}", sessionId, userType, status.getReason());
        
        if ("admin".equals(userType) && userId != null) {
            connectionManager.unregisterAdmin(userId);
        } else if ("client".equals(userType)) {
            connectionManager.unregisterClient(sessionId);
        }
        
        sessionTypes.remove(sessionId);
        sessionUsers.remove(sessionId);
    }
    
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        String sessionId = session.getId();
        logger.error("WebSocket传输错误: {} - {}", sessionId, exception.getMessage());
        
        // 发送错误消息
        Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                "连接发生错误: " + exception.getMessage());
        sendMessage(session, errorMsg);
    }
    
    /**
     * 处理服务端用户消息
     */
    private void handleAdminMessage(WebSocketSession session, Message message) {
        String adminId = sessionUsers.get(session.getId());
        
        switch (message.getType()) {
            case CONNECT_REQUEST:
                // 服务端用户处理连接请求
                String clientSessionId = message.getSessionId();
                if (clientSessionId != null) {
                    // 根据消息内容决定接受或拒绝
                    String content = message.getContent();
                    if ("accept".equals(content)) {
                        // 接受连接
                        boolean success = connectionManager.acceptConnection(adminId, clientSessionId);
                        if (!success) {
                            Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                                    "无法接受连接，可能您已有活跃连接或请求不存在");
                            sendMessage(session, errorMsg);
                        }
                    } else if ("reject".equals(content)) {
                        // 拒绝连接
                        boolean success = connectionManager.rejectConnection(adminId, clientSessionId);
                        if (!success) {
                            Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                                    "无法拒绝连接，可能请求不存在");
                            sendMessage(session, errorMsg);
                        }
//                        message.setType(Message.MessageType.CONNECT_FAILD);
//                        sendMessage(session, message);
                    } else {
                        // 默认接受连接（向后兼容）
                        boolean success = connectionManager.acceptConnection(adminId, clientSessionId);
                        if (!success) {
                            Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                                    "无法接受连接，可能您已有活跃连接或请求不存在");
                            sendMessage(session, errorMsg);
                        }
                    }
                }
                break;
                
            case CONNECT_RELEASE:
                // 服务端用户释放连接
                String connectedClientId = connectionManager.getActiveConnections().get(adminId);
                if (connectedClientId != null) {
                    connectionManager.releaseConnection(adminId, connectedClientId);
                }
                break;
                
            case CHAT_MESSAGE:
                // 聊天消息
                String targetClientId = connectionManager.getActiveConnections().get(adminId);
                if (targetClientId != null) {
                    Message chatMsg = new Message(Message.MessageType.CHAT_MESSAGE, adminId, message.getContent());
                    connectionManager.sendToClient(targetClientId, chatMsg);
                } else {
                    Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                            "您当前没有活跃连接，无法发送消息");
                    sendMessage(session, errorMsg);
                }
                break;
            case CONNECT_SUCCESS:
                message.setType(Message.MessageType.CONNECT_SUCCESS);
                sendMessage(session, message);
                connectionManager.sendToClient(message.getSessionId(),message);
                break;
            case REJECT_REQUEST:
                message.setType(Message.MessageType.REJECT_REQUEST);
                sendMessage(session, message);
                connectionManager.sendToClient(message.getSessionId(),message);
                break;
            case REMOVE_CONNECTED_REQUEST:
                //特殊处理，发此类消息是指已经连接成功了，但是要清楚客户端请求
                message.setSessionId(session.getId());
                sendMessage(session, message);
                connectionManager.sendToClient(message.getSessionId(),message);

                break;
            default:
                logger.warn("未知的消息类型: {}", message.getType());
        }
    }
    
    /**
     * 处理客户端消息
     */
    private void handleClientMessage(WebSocketSession session, Message message) {
        String clientSessionId = session.getId();
        logger.info("处理客户端消息: {} 来自会话: {}", message.getType(), clientSessionId);
        
        switch (message.getType()) {
            case CONNECT_REQUEST:
                // 客户端申请连接
                String clientName = message.getFrom();
                if (clientName == null || clientName.trim().isEmpty()) {
                    clientName = "客户端-" + clientSessionId.substring(0, 8);
                }
                
                logger.info("客户端申请连接: {} ({})", clientName, clientSessionId);
                boolean success = connectionManager.addConnectionRequest(clientSessionId, clientName, session);
                logger.info("连接请求处理结果: {}", success);
                
                if (success) {
                    Message confirmMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                            "连接请求已发送，请等待服务端用户处理");
                    sendMessage(session, confirmMsg);
                } else {
                    Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                            "您已在连接队列中，请耐心等待");
                    sendMessage(session, errorMsg);
                }
                break;
                
            case CHAT_MESSAGE:
                // 客户端发送聊天消息
                String adminId = connectionManager.getActiveConnections().entrySet().stream()
                        .filter(entry -> entry.getValue().equals(clientSessionId))
                        .map(Map.Entry::getKey)
                        .findFirst()
                        .orElse(null);
                
                if (adminId != null) {
                    Message chatMsg = new Message(Message.MessageType.CHAT_MESSAGE, clientSessionId, message.getContent());
                    connectionManager.sendToAdmin(adminId, chatMsg);
                } else {
                    Message errorMsg = new Message(Message.MessageType.SYSTEM_MESSAGE, "系统", 
                            "您当前没有活跃连接，无法发送消息");
                    sendMessage(session, errorMsg);
                }
                break;
                
            default:
                logger.warn("未知的消息类型: {}", message.getType());
        }
    }
    
    /**
     * 发送消息给指定会话
     */
    private void sendMessage(WebSocketSession session, Message message) {
        try {
            if (session != null && session.isOpen()) {
                String jsonMessage = objectMapper.writeValueAsString(message);
                logger.info("发送消息: 会话ID={}, 消息={}", session.getId(), jsonMessage);
                if (jsonMessage.contains("REJECT_REQUEST")) {
                    Message adminListMsg = new Message(Message.MessageType.REMOVE_CONNECTED_REQUEST, "", "",message.getSessionId());
                    connectionManager.broadcastToAdmins(adminListMsg);
                }
                session.sendMessage(new TextMessage(jsonMessage));
                logger.info("消息发送成功: 会话ID={}", session.getId());
            } else {
                logger.warn("尝试向已关闭的会话发送消息: 会话ID={}, 会话状态={}", 
                    session != null ? session.getId() : "null", 
                    session != null ? (session.isOpen() ? "OPEN" : "CLOSED") : "NULL");
            }
        } catch (IOException e) {
            logger.error("发送消息失败: 会话ID={}, 错误={}", 
                session != null ? session.getId() : "null", e.getMessage(), e);
        }
    }
    
    /**
     * 广播在线管理员更新给所有服务端用户
     */
    private void broadcastOnlineAdminsUpdate() {
        List<String> onlineAdmins = connectionManager.getOnlineAdmins();
        Message adminListMsg = new Message(Message.MessageType.ONLINE_ADMINS, "系统", "");
        adminListMsg.setAdmins(onlineAdmins);
        
        // 广播给所有服务端用户
        connectionManager.broadcastToAdmins(adminListMsg);
        logger.info("广播在线管理员更新: {}", onlineAdmins);
    }

    public static String getNowStr() {
        // 创建 SimpleDateFormat 对象，指定目标格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 将时间戳转换为 Date 对象
        Date date = new Date();
        // 格式化日期并返回
        return sdf.format(date);
    }
} 
